package com.xiao.pool;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Xiao
 * @version 1.0
 * @description 数据源连接池
 * @date 2022/1/2 22:30
 */
public class MyDataSource extends MyAbstractDataSource{
    //空闲连接池
    private final List<ConnectionProxy> idleConnections = new ArrayList<>();
    //激活的连接池
    private final List<ConnectionProxy> activeConnections = new ArrayList<>();
    //监视器对象：做一些同步的操作，保证线程安全
    private final Object monitor = new Object();

    /**
     * 覆盖父类的getConnection()方法，返回一个动态代理连接对象
     * @return
     * @throws SQLException
     */
    @Override
    public Connection getConnection() throws SQLException {
        ConnectionProxy connectionProxy = getConnectionProxy(super.getUsername(), super.getPassword());
        return connectionProxy.getProxyConnection();
    }

    /**
     * 获取连接代理对象
     * @param username
     * @param password
     * @return
     */
    private ConnectionProxy getConnectionProxy(String username, String password) throws SQLException {
        //是否需要等待
        boolean wait = false;
        //刚开始没有连接
        ConnectionProxy connectionProxy = null;
        while (connectionProxy == null) {
            //做一个同步锁，保证线程安全
            synchronized (monitor) {
                //如果空闲连接池不为空，直接从空闲连接池获取连接
                if (!idleConnections.isEmpty()) {
                    connectionProxy = idleConnections.remove(0);
                } else {
                    //没有空闲连接可用时，需要创建新的连接
                    if (activeConnections.size() < super.getPoolMaxActiveSize()) {
                        //如果当前激活的连接数小于最大连接数，直接创建新连接
                        connectionProxy = new ConnectionProxy(super.getConnection(), this);
                    }
                }
            }
            //如果当前激活的连接数不小于最大连接数，需要等待（poolTimeToWait）
            if (!wait) {
                wait = true;
            }
            if (connectionProxy == null) {
                //通过上面的步骤(sync内的逻辑)后，未能获取连接对象 --> 等待
                try {
                    monitor.wait(super.getPoolTimeToWait());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //等待被线程打断，退出循环
                    break;
                }
            }
        }
        if (connectionProxy != null) {
            //如果连接对象不为null，说明已经成功获取连接对象，放入激活的连接池
            activeConnections.add(connectionProxy);
        }
        return connectionProxy;
    }

    /**
     * 关闭连接：把连接从激活连接池归还到空闲连接池
     * @param connectionProxy
     */
    public void closeConnection(ConnectionProxy connectionProxy) {
        synchronized (monitor) {
            //关闭连接时，把激活状态的连接放入空闲连接池
            activeConnections.remove(connectionProxy);
            if (idleConnections.size() < super.getPoolMaxIdleSize()) {
                idleConnections.add(connectionProxy);
            }
            //此时已有空闲线程，执行notifyAll()方法唤醒等待获取连接的线程
            monitor.notifyAll();
        }
    }
}
